﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GeneralDFS.BusinessLogical.FileSystemLogical;
using GeneralDFS.BusinessLogical.IO;
using GeneralDFS.BusinessLogical.Network;
using GeneralDFS.BusinessLogical.Protocol;
using GeneralDFS.Client;
using GeneralDFS.Common.IO;
using GeneralDFS.DataEntity.IO;
using GeneralDFS.DataEntity.Enum;
using System.Threading;

namespace GeneralDFS.CommandLineTools
{
    class Program
    {
        private static Client.Client _client;
        private static String _currentPath;
        private static DirectoryNodeInfo _currentNode;
        private static List<TestResult> _results;

        [STAThread]
        static void Main(string[] args)
        {
            _client = new Client.Client();
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Welecome to use this CommandTool.Type exit to exit the program");
            Console.WriteLine("Current Time is " + DateTime.Now);
            
            _currentPath = "";
            while (true)
            {
                Console.Write("GeneralDFS>");
                var command = new ParseCommand(Console.ReadLine());
                if (command.Command == "exit") return;
                if (command.Command == "ls")
                {
                    _currentNode =
                        _client.GetRemoteObjectDirect(_currentPath).GetNodeByPath(_currentPath) as DirectoryNodeInfo;
                    if (_currentNode == null || !_currentNode.IsDirectory()) break;
                    var directory = new Directory(_currentNode);
                    var nodeBasics = _currentNode.Childs;
                    foreach (var nodeBasic in nodeBasics)
                    {
                        Console.WriteLine(" {0}   {1}", nodeBasic.Name, nodeBasic.LastUpdateTime);
                    }
                    Console.WriteLine("Total:{0} Items", nodeBasics.Count);
                }
                else if (command.Command == "mkdir")
                {
                    _client.GetRemoteObjectDirect(_currentPath)
                           .CreateDirectoryByPath(_currentPath + @"/" + command.Args[0]);
                }
                else if (command.Command == "pwd")
                {
                    Console.ForegroundColor = ConsoleColor.DarkGreen;
                    Console.WriteLine(_currentPath);
                    Console.ForegroundColor = ConsoleColor.White;
                }
                else if (command.Command == "cd")
                {
                    if (command.Args[0] == "..")
                    {
                        if (_currentPath != "")
                        {
                            _currentPath = _currentPath.Substring(0,
                                                                  _currentPath.LastIndexOf(@"/",
                                                                                           System.StringComparison
                                                                                                 .Ordinal));
                        }
                    }
                    var temp = PathHelper.Combine(_currentPath, command.Args[0]);
                    if (_client.GetRemoteObjectDirect(_currentPath).GetNodeByPath(temp) != null)
                        _currentPath = temp;
                }
                else if (command.Command == "push")
                {
                    FileDialog fileDialog = new OpenFileDialog()
                        {
                            CheckFileExists = true,
                            CheckPathExists = true,
                            RestoreDirectory = true
                        };

                    if (fileDialog.ShowDialog(new Form()) == DialogResult.OK)
                    {
                        String fullPath = fileDialog.FileName.Replace(@"/", @"\");
                        ;
                        String fileName =
                            fullPath.Substring(fullPath.LastIndexOf(@"\", System.StringComparison.Ordinal) + 1);
                        var stream = new DFSInputStream(PathHelper.Combine(_currentPath, fileName), _client);
                        stream.WriteFile(fullPath);
                        stream.Close();
                    }
                }
                else if (command.Command == "print")
                {
                    if (command.Args.Length == 0)
                    {
                        Console.WriteLine("No FileName");
                        return;
                    }
                    var fileNodeInfo =
                        _client.GetRemoteObjectDirect(_currentPath)
                               .GetNodeByPath(PathHelper.Combine(_currentPath, command.Args[0])) as FileNodeInfo;
                    if (fileNodeInfo != null)
                        foreach (var blockInfo in fileNodeInfo.Blocks)
                        {
                            Console.WriteLine("Guid:{0} FirstDataNodeName:{1}", blockInfo.Guid,
                                              blockInfo.DataNodeList[0].Name);
                        }
                }
                else if (command.Command == "get")
                {
                    if (command.Args.Length == 0)
                    {
                        Console.WriteLine("No FileName");
                        return;
                    }
                    var path = System.IO.Path.Combine(System.Environment.CurrentDirectory, command.Args[0]);
                    Console.WriteLine(path);
                    var output = new DFSOutputStream(PathHelper.Combine(_currentPath, command.Args[0]), _client);
                    output.ReadFile(path);
                }
                else if (command.Command == "rm")
                {
                    if (command.Args.Length == 0)
                    {
                        Console.WriteLine("No FileName");
                        return;
                    }
                    if (command.Args.Length == 1 || command.Args[0] != "-d")
                        _client.GetRemoteObjectDirect(_currentPath)
                               .DeleteNodeByPath(PathHelper.Combine(_currentPath, command.Args[0]), NodeBaseType.File);
                    else if (command.Args[0] == "-d")
                        _client.GetRemoteObjectDirect(_currentPath)
                               .DeleteNodeByPath(PathHelper.Combine(_currentPath, command.Args[1]),
                                                 NodeBaseType.Directory);
                }
                else if (command.Command == "testnn")
                {
                    _results = new List<TestResult>();

                    //模拟同时有多少个用户
                    for (int i = 0; i < 80; i++)
                    {
                        TestDelegate dDelegate = new TestDelegate(Test);
                        dDelegate.BeginInvoke(i, new AsyncCallback(delegate
                            {
                                lock (_results)
                                {
                                    var file = System.IO.File.CreateText("result.txt");
                                    Console.WriteLine(_results.Count);
                                    foreach (TestResult result in _results)
                                    {
                                        file.WriteLine(result.Num + "|" + result.Time);
                                    }
                                    file.Close();
                                }
                            }), null);
                    }
                    while (count < MaxCount)
                    {

                    }

                }
                else if (command.Command == "save")
                {

                    FileDialog fileDialog = new OpenFileDialog() { CheckFileExists = true, CheckPathExists = true, RestoreDirectory = true };
                    if (fileDialog.ShowDialog(new Form()) == DialogResult.OK)
                    {
                        DateTime begin = DateTime.Now;
                        //Task[] task = new Task[1000];
                        for (int i = 0; i < 10; i++)
                        {
                            //task[i] = PushFile(i.ToString(), fileDialog);
                            String fullPath = fileDialog.FileName.Replace(@"/", @"\");
                            var stream = new DFSInputStream(PathHelper.Combine(_currentPath, i.ToString()), _client);
                            stream.WriteFile(fullPath);
                            stream.Close();
                        }
                        //Task.WaitAll(task);
                        Console.WriteLine((DateTime.Now - begin).TotalSeconds);
                    }
                }
                else if (command.Command == "te")
                {

                    DateTime begin = DateTime.Now;
                    for (int i = 0; i < 10; i++)
                    {
                        var path = System.IO.Path.Combine(System.Environment.CurrentDirectory, i.ToString());
                        var output = new DFSOutputStream(PathHelper.Combine(_currentPath, i.ToString()), _client);

                        output.ReadFile(path);

                    }
                    Console.WriteLine((DateTime.Now - begin).TotalSeconds);
                }

            }
        }

            private static readonly
            object SequenceLock = new object();

        private static int count = 0;
        private static int count2 = 0;

        private const int MaxCount=100;
        
        delegate void TestDelegate(int i);

        private static void Test(int num)
        {
            while (count < MaxCount)
            {
                lock(_results)
                {
                    DateTime begin = DateTime.Now;
                    DFSOutputStream dfsOutputStream =
                        new DFSOutputStream(PathHelper.Combine(_currentPath, count2.ToString()), _client);
                    TestResult result = new TestResult {Time = (DateTime.Now - begin).TotalSeconds, Num = num};
                    _results.Add(result);
                    //Console.WriteLine(count);
                    count++;
                    count2++;
                    if (count2 >= 100)
                        count2 = 0;
                }
                
        }
    }
        public static async Task GetFile(string fileName)
        {
            var path = System.IO.Path.Combine(System.Environment.CurrentDirectory, fileName);
            var output = new DFSOutputStream(PathHelper.Combine(_currentPath, fileName), _client);
            output.ReadFile(path);
        }
    }
}